/*
	Copyright 2009 Omer Saatcioglu
	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at

		http://www.apache.org/licenses/LICENSE-2.0

	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.

	$Author$
	$Revision$
	$LastChangedDate$
   
 */

package com.saatcioglu.android.guessthenumber;

import java.util.ArrayList;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ListActivity;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Vibrator;
import android.util.Log;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class GfxGuesstheNumber extends ListActivity implements OnClickListener{

	static final protected int NEWGAME_ID = Menu.FIRST;
	static final protected int SHOWMETHENUMBER_ID = Menu.FIRST + 1;
	static final protected int ABOUT_ID = Menu.FIRST + 3;
	static final protected int EXIT_ID = Menu.FIRST + 4;
	
	static final protected int NOTSURE_ID = Menu.FIRST + 11;
	static final protected int DEFINITELY_ID = Menu.FIRST + 12;
	static final protected int MAYBE_ID = Menu.FIRST + 13;
	static final protected int NOTACHANCE_ID = Menu.FIRST + 14;
	
	static private GfxGuesstheNumber gfxGuesstheNumber = null;

	private ArrayList<String> mStrings = new ArrayList<String>();
	private ArrayAdapter<String> mAdapter;
	private Vibrator vibrator;
	private TextView txtviewCount;
	private Button mSelectedButton;
	protected Button btnClear;
	protected Button btnEnter;
	protected Button[] arrbtnNumbers = new Button[10];
	private MyChronometer chronMain;
	protected EditText edtNewNumber;
	private int intCounter;
	private int theDigitsPressed;
	private int[] arrintPrevButtons;

	static public GfxGuesstheNumber getInstance() {
		if (gfxGuesstheNumber == null) {
			Log.d("GfxGuesstheNumber::getInstance", "gfxGuesstheNumber = null");
		}
		return gfxGuesstheNumber;
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		preparePreference();
		super.onCreate(savedInstanceState);
		this.setTitle(getString(R.string.app_name)
				+ getString(R.string.abbr_version)
				+ getString(R.string.app_version));
		setContentView(R.layout.guessthenumber);
		SetDisplayElements();
		StartaNewGame();
		CtrlMaintanence.getInstance().resumetheGame();
		UpdateDisplayElements();
		gfxGuesstheNumber = this;
	}

	@Override
	protected void onPause() {
		chronMain.pause();
		super.onPause();
	}

	@Override
	protected void onResume() {
		chronMain.resume();
		super.onResume();
	}

	@Override
	protected void onDestroy() {
		if (SMBGuesstheNumber.isGameStarted) {
			savetheGame();
		}
		CtrlMaintanence.getInstance().savetheGame();
		super.onDestroy();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		menu.add(0, NEWGAME_ID, 0, R.string.newgame);
		menu.add(0, SHOWMETHENUMBER_ID, 0, R.string.showmethenumber);
		menu.add(0, ABOUT_ID, 0, R.string.about);
		menu.add(0, EXIT_ID, 0, R.string.exit);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case NEWGAME_ID:
			SMBGuesstheNumber.isGameStarted = false;
			StartaNewGame();
			return true;
		case SHOWMETHENUMBER_ID:
			SMBGuesstheNumber.isGameStarted = false;
			ShowmetheNumber();
			return true;
		case ABOUT_ID:
			showDialog(R.id.display_hints);
			return true;
		case EXIT_ID:
			finish();
			return true;
		}
		return super.onOptionsItemSelected(item);
	}

	@Override
	public void onClick(View v) {
		switch (((Button) v).getId()) {
		case R.id.enter:
			entertheNumber();
			break;
		case R.id.clear:
			cleartheNumber();
			break;
		case R.id.number_zero:
		case R.id.number_one:
		case R.id.number_two:
		case R.id.number_three:
		case R.id.number_four:
		case R.id.number_five:
		case R.id.number_six:
		case R.id.number_seven:
		case R.id.number_eight:
		case R.id.number_nine:
			addtotheNumber(edtNewNumber, (Button) v);
			break;
		}
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
		case R.id.display_hints:
			return new AlertDialog.Builder(this).setIcon(R.drawable.droid)
					.setTitle(R.string.dialog_hint_title).setMessage(
							R.string.dialog_hint_text).setPositiveButton(
							R.string.OK, new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog,
										int whichButton) {
								}
							}).create();
		}
		return null;
	}

	protected void StartaNewGame() {
		arrintPrevButtons = new int[SMBGuesstheNumber.nActiveDigits];
		CtrlGuesstheNumber.getInstance().setDigitNumber(SMBGuesstheNumber.nActiveDigits);
		CtrlGuesstheNumber.getInstance().settheSecretNumber();
		theDigitsPressed = 0;

		for (int i = 1; i < 10; i++) {
			arrbtnNumbers[i].setEnabled(true);
		}
		arrbtnNumbers[0].setEnabled(false);
		edtNewNumber.setText("");
		mAdapter.clear();
		btnEnter.setEnabled(false);
		btnClear.setEnabled(false);
		chronMain.stop();
		chronMain.reset();
		intCounter = 0;
		txtviewCount.setText(getString(R.string.totalshots)
				+ Integer.toString(intCounter));
		for (int i = 0; i < 10; i++) {
			arrbtnNumbers[i].setTextColor(Color.BLACK);
			SMBGuesstheNumber.arrintBtnNumberStates[i] = 0;
		}
	}

	protected void ShowmetheNumber() {
		edtNewNumber.setText(Integer.toString(CtrlGuesstheNumber.getInstance().gettheSecretNumber()));
		for (int i = 0; i < 10; i++) {
			arrbtnNumbers[i].setEnabled(false);
		}
		btnEnter.setEnabled(false);
		btnClear.setEnabled(false);
		chronMain.stop();
	}

	private void addtotheNumber(EditText theNumber, Button theButtonPressed) {

		theNumber.append(theButtonPressed.getText().toString());
		theButtonPressed.setEnabled(false);
		arrintPrevButtons[theDigitsPressed++] = Integer
				.parseInt(theButtonPressed.getText().toString());

		if (theNumber.getText().toString().length() == 1) {
			arrbtnNumbers[0].setEnabled(true);
			btnClear.setEnabled(true);
		}

		if (theNumber.getText().toString().length() == SMBGuesstheNumber.nActiveDigits) {
			for (int i = 0; i < 10; i++) {
				arrbtnNumbers[i].setEnabled(false);
			}
			btnEnter.setEnabled(true);
		}
		chronMain.start();
		SMBGuesstheNumber.isGameStarted = true;
	}

	private void cleartheNumber() {

		edtNewNumber.setText(edtNewNumber.getText().toString().substring(0,
				edtNewNumber.getText().toString().length() - 1));
		if (edtNewNumber.getText().toString().length() == SMBGuesstheNumber.nActiveDigits - 1) {
			for (int i = 0; i < 10; i++) {
				arrbtnNumbers[i].setEnabled(true);
			}
			theDigitsPressed--;
			for (int i = 0; i < theDigitsPressed; i++) {
				arrbtnNumbers[arrintPrevButtons[i]].setEnabled(false);
			}
			btnEnter.setEnabled(false);
		} else {
			arrbtnNumbers[arrintPrevButtons[--theDigitsPressed]]
					.setEnabled(true);
		}

		if (edtNewNumber.getText().toString().length() == 0) {
			arrbtnNumbers[0].setEnabled(false);
			btnClear.setEnabled(false);
		}
	}

	protected void entertheNumber() {

		int[] theResult = CtrlGuesstheNumber.getInstance().ProcesstheNumber(
				Integer.parseInt(edtNewNumber.getText().toString()));
		mAdapter.add(getString(R.string.margin) + getString(R.string.plus)
				+ theResult[0] + getString(R.string.minus) + theResult[1]
				+ getString(R.string.gap) + edtNewNumber.getText().toString());
		edtNewNumber.setText("");
		for (int i = 1; i < 10; i++) {
			arrbtnNumbers[i].setEnabled(true);
		}
		arrbtnNumbers[0].setEnabled(false);
		theDigitsPressed = 0;
		btnEnter.setEnabled(false);
		btnClear.setEnabled(false);
		intCounter++;
		txtviewCount.setText(getString(R.string.totalshots)
				+ Integer.toString(intCounter));

		if (theResult[0] == SMBGuesstheNumber.nActiveDigits && theResult[1] == 0) {
			gameSucceded();
		} else if (SMBGuesstheNumber.nActiveMaxShots != 0 && intCounter == SMBGuesstheNumber.nActiveMaxShots) {
			gameFailed();
		}
	}

	public void gameFailed() {
		SMBGuesstheNumber.isGameStarted = false;
		CtrlMaintanence.getInstance().savetheGame();
		ShowmetheNumber();
		vibrator.vibrate(100);
		removeDialog(R.id.display_failure);
		showDialog(R.id.display_failure);
	}

	protected void gameSucceded() {
		SMBGuesstheNumber.isGameStarted = false;
		ShowmetheNumber();
		vibrator.vibrate(100);
	}

	private void SetDisplayElements() {

		mAdapter = new ArrayAdapter<String>(this,
				android.R.layout.simple_list_item_1, mStrings) {
			@Override
			public View getView(int position, View convertView, ViewGroup parent) {
				TextView txtView = new TextView(this.getContext());
				txtView.setTextSize(16);
				txtView.setText(this.getItem(position));
				return txtView;
			}
		};

		setListAdapter(mAdapter);
		getListView().setTextFilterEnabled(true);
		edtNewNumber = (EditText) findViewById(R.id.userText);
		txtviewCount = (TextView) findViewById(R.id.TextViewCount);
		chronMain = (MyChronometer) findViewById(R.id.ChronometerStart);
		vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
		arrbtnNumbers[0] = (Button) findViewById(R.id.number_zero);
		arrbtnNumbers[1] = (Button) findViewById(R.id.number_one);
		arrbtnNumbers[2] = (Button) findViewById(R.id.number_two);
		arrbtnNumbers[3] = (Button) findViewById(R.id.number_three);
		arrbtnNumbers[4] = (Button) findViewById(R.id.number_four);
		arrbtnNumbers[5] = (Button) findViewById(R.id.number_five);
		arrbtnNumbers[6] = (Button) findViewById(R.id.number_six);
		arrbtnNumbers[7] = (Button) findViewById(R.id.number_seven);
		arrbtnNumbers[8] = (Button) findViewById(R.id.number_eight);
		arrbtnNumbers[9] = (Button) findViewById(R.id.number_nine);
		btnEnter = (Button) findViewById(R.id.enter);
		btnClear = (Button) findViewById(R.id.clear);
		for (int i = 0; i < 10; i++) {
			arrbtnNumbers[i].setOnClickListener(this);
			registerForContextMenu(arrbtnNumbers[i]);
		}
		btnEnter.setOnClickListener(this);
		btnClear.setOnClickListener(this);
	}

	private void UpdateDisplayElements() {

		if (SMBGuesstheNumber.bShowTotalShots) {
			txtviewCount.setVisibility(View.VISIBLE);
		} else {
			txtviewCount.setVisibility(View.INVISIBLE);
		}

		if (SMBGuesstheNumber.bShowElapsedTime) {
			chronMain.setVisibility(View.VISIBLE);
		} else {
			chronMain.setVisibility(View.INVISIBLE);
		}
		if (!SMBGuesstheNumber.bDisplayFlagList) {
			for (int i = 0; i < 10; i++) {
				arrbtnNumbers[i].setTextColor(Color.BLACK);
			}
		}
	}

	protected void resumetheGame() {
		edtNewNumber.setText(SMBGuesstheNumber.mEditorText);
		for (String strGuess : SMBGuesstheNumber.mStrings) {
			mAdapter.add(strGuess);
		}
		intCounter = SMBGuesstheNumber.intCounter;
		theDigitsPressed = SMBGuesstheNumber.theDigitsPressed;
		arrintPrevButtons = SMBGuesstheNumber.arrintPrevButtons;

		for (int i = 0; i < 10; i++) {
			arrbtnNumbers[i]
					.setEnabled(SMBGuesstheNumber.arrisBtnNumberEnabled[i]);
			switch (SMBGuesstheNumber.arrintBtnNumberStates[i]) {
			case 0:
				arrbtnNumbers[i].setTextColor(Color.BLACK);
				break;
			case 1:
				arrbtnNumbers[i].setTextColor(Color.GREEN);
				break;
			case 2:
				arrbtnNumbers[i].setTextColor(Color.YELLOW);
				break;
			case 3:
				arrbtnNumbers[i].setTextColor(Color.RED);
				break;
			}
		}
		btnClear.setEnabled(SMBGuesstheNumber.arrisBtnNumberEnabled[10]);
		btnEnter.setEnabled(SMBGuesstheNumber.arrisBtnNumberEnabled[11]);
		txtviewCount.setText(getString(R.string.totalshots)
				+ Integer.toString(intCounter));
		chronMain.start(SMBGuesstheNumber.lngElapsedTime);
		CtrlGuesstheNumber.getInstance().setDigitNumber(SMBGuesstheNumber.nActiveDigits);
		CtrlGuesstheNumber.getInstance().settheSecretNumber(SMBGuesstheNumber.intSecretNumber);

	}

	protected void savetheGame() {

		SMBGuesstheNumber.mEditorText = edtNewNumber.getText().toString();
		SMBGuesstheNumber.mStrings = mStrings;
		SMBGuesstheNumber.intCounter = intCounter;
		SMBGuesstheNumber.theDigitsPressed = theDigitsPressed;
		SMBGuesstheNumber.arrintPrevButtons = arrintPrevButtons;
		for (int i = 0; i < 10; i++) {
			SMBGuesstheNumber.arrisBtnNumberEnabled[i] = arrbtnNumbers[i]
					.isEnabled();
		}
		SMBGuesstheNumber.arrisBtnNumberEnabled[10] = btnClear.isEnabled();
		SMBGuesstheNumber.arrisBtnNumberEnabled[11] = btnEnter.isEnabled();
		SMBGuesstheNumber.lngElapsedTime = chronMain.getElapsedTime();
		SMBGuesstheNumber.intSecretNumber = CtrlGuesstheNumber.getInstance().gettheSecretNumber();
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		menu.setHeaderIcon(R.drawable.droid);
		menu.setHeaderTitle(R.string.contextmenu_flaglist);
		menu.add(0, NOTSURE_ID, 0, R.string.contextmenu_flaglist_notsure);
		menu.add(0, DEFINITELY_ID, 0, R.string.contextmenu_flaglist_definitely);
		menu.add(0, MAYBE_ID, 0, R.string.contextmenu_flaglist_maybe);
		menu.add(0, NOTACHANCE_ID, 0, R.string.contextmenu_flaglist_notachance);
		mSelectedButton = (Button) v;
		super.onCreateContextMenu(menu, v, menuInfo);
	}

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		SMBGuesstheNumber.arrintBtnNumberStates[Integer.parseInt(mSelectedButton.getText().toString())] 
		                                        = item.getItemId() - NOTSURE_ID;
		switch (item.getItemId()) {
		case NOTSURE_ID:
			mSelectedButton.setTextColor(Color.BLACK);
			return true;
		case DEFINITELY_ID:
			mSelectedButton.setTextColor(Color.GREEN);
			return true;
		case MAYBE_ID:
			mSelectedButton.setTextColor(Color.YELLOW);
			return true;
		case NOTACHANCE_ID:
			mSelectedButton.setTextColor(Color.RED);
			return true;
		}
		return super.onContextItemSelected(item);
	}

	protected void preparePreference() {
		// virtual method. it is overwritten by the sub classes.		
	}
	
	protected String formatMission(){
		String message = new String();

		message = getString(R.string.text_gen_mission)
		+ getString(R.string.text_gen_number1)
		+ CtrlMaintanence.getInstance().formatShots(SMBGuesstheNumber.nActiveDigits)
		+ getString(R.string.text_gen_number2);
		
		boolean isMaxShotsNonZero = (SMBGuesstheNumber.nActiveMaxShots >0); 
		if(isMaxShotsNonZero){
			message = message 
			+ getString(R.string.text_gen_shots1)
			+ CtrlMaintanence.getInstance().formatShots(SMBGuesstheNumber.nActiveMaxShots)
			+ getString(R.string.text_gen_shots2);
		}
		if(SMBGuesstheNumber.nActiveMaxTime > 0){
			if(isMaxShotsNonZero){
				message = message 
				+ getString(R.string.text_gen_number3);
			}
			message = message 
			+ getString(R.string.text_gen_time1)
			+ CtrlMaintanence.getInstance().formatTime(SMBGuesstheNumber.nActiveMaxTime)
			+ getString(R.string.text_gen_time2);
			if(isMaxShotsNonZero){
				message = message 
				+ getString(R.string.text_gen_number4);
			}
		}
		else{
			if(isMaxShotsNonZero){
				message += _formatMissionTimeMasterShot();
			} else{
				message += _formatMissionTimeandMaxMasterShot();
			}
		}
		return message;
	}
	
	protected String _formatMissionTimeMasterShot(){
		// it will be overwritten by GfxMasterShot only.
		return "";
	}
	protected String _formatMissionTimeandMaxMasterShot(){
		// it will be overwritten by GfxMasterShot only.
		return "";
	}

}